/*
 * ConnectionFrame.java
 *
 * Created on 12/12/2011, 22:10:42
 */

package br.mg.bhe.ftpobre.gui.connection;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.File;
import java.io.IOException;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;

import br.mg.bhe.ftpobre.ConnectionData;
import br.mg.bhe.ftpobre.Main;
import br.mg.bhe.ftpobre.command.facade.ServerFacade;
import br.mg.bhe.ftpobre.fs.data.xml.XmlFacade;
import br.mg.bhe.ftpobre.gui.MainFrame;
import br.mg.bhe.ftpobre.gui.fs.FileTableModelBuilder;
import br.mg.bhe.ftpobre.log.FtpLogView;
import br.mg.bhe.ftpobre.util.LocalFileUtil;
import br.mg.bhe.ftpobre.util.LogUtil;
import br.mg.bhe.ftpobre.util.MensagensUtil;

/**
 *
 * @author Aureliano
 */
public class ConnectionFrame extends javax.swing.JDialog {

	private static final Logger logger = LogUtil.getLogger(ConnectionFrame.class);
	
    /** Creates new form ConnectionFrame */
    public ConnectionFrame(java.awt.Frame parent, boolean modal, boolean newDataConnection) {
        super(parent, modal);
        this.newDataConnection = newDataConnection;
        initComponents();
        super.addWindowListener(new WindowAction());
        this.buttonConnect.addActionListener(new ConnectAction());
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        labelUser = new javax.swing.JLabel();
        textFieldUser = new javax.swing.JTextField();
        labelPassword = new javax.swing.JLabel();
        passwordField = new javax.swing.JPasswordField();
        labelHost = new javax.swing.JLabel();
        textFieldHost = new javax.swing.JTextField();
        labelPort = new javax.swing.JLabel();
        textFieldPort = new javax.swing.JTextField();
        buttonConnect = new javax.swing.JButton();
        buttonCancel = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Conexão FTP");
        setResizable(false);

        labelUser.setText("Usuário:");

        labelPassword.setText("Senha:");

        labelHost.setText("Host:");

        labelPort.setText("Porta:");

        buttonConnect.setText("Conectar");
        buttonConnect.setPreferredSize(new java.awt.Dimension(90, 25));

        buttonCancel.setText("Cancelar");
        buttonCancel.setPreferredSize(new java.awt.Dimension(90, 25));
        buttonCancel.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonCancelActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(layout.createSequentialGroup()
                        .addComponent(labelUser)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(textFieldUser, javax.swing.GroupLayout.DEFAULT_SIZE, 330, Short.MAX_VALUE))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(labelPassword)
                            .addComponent(labelHost)
                            .addComponent(labelPort))
                        .addGap(18, 18, 18)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(textFieldHost, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
                            .addComponent(passwordField, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
                            .addComponent(textFieldPort, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addComponent(buttonConnect, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(buttonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labelUser)
                    .addComponent(textFieldUser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labelPassword)
                    .addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(labelHost)
                    .addComponent(textFieldHost, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(textFieldPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(labelPort))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(buttonCancel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(buttonConnect, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-416)/2, (screenSize.height-187)/2, 416, 187);
    }// </editor-fold>//GEN-END:initComponents

    private void buttonCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCancelActionPerformed
        dispose();
    }//GEN-LAST:event_buttonCancelActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonCancel;
    private javax.swing.JButton buttonConnect;
    private javax.swing.JLabel labelHost;
    private javax.swing.JLabel labelPassword;
    private javax.swing.JLabel labelPort;
    private javax.swing.JLabel labelUser;
    private javax.swing.JPasswordField passwordField;
    private javax.swing.JTextField textFieldHost;
    private javax.swing.JTextField textFieldPort;
    private javax.swing.JTextField textFieldUser;
    // End of variables declaration//GEN-END:variables
    private boolean newDataConnection;

    private class WindowAction implements WindowListener {

		@Override
		public void windowActivated(WindowEvent arg0) {		}

		@Override
		public void windowClosed(WindowEvent arg0) {		}

		@Override
		public void windowClosing(WindowEvent arg0) {		}

		@Override
		public void windowDeactivated(WindowEvent arg0) {		}

		@Override
		public void windowDeiconified(WindowEvent arg0) {		}

		@Override
		public void windowIconified(WindowEvent arg0) {		}

		@Override
		public void windowOpened(WindowEvent evt) {
                    if (newDataConnection) {
                        return;
                    }

                    try {
                        this.loadConnectionPreferences();
                    } catch (Exception ex) {
                        MensagensUtil.showErrorMessage(
                                        "Erro", "Não foi possível carregar dados da última conexão. Detalhe: " + ex.getMessage());
                        FtpLogView.log("Não foi possível carregar dados da última conexão.");
                        logger.log(Level.SEVERE, ex.getMessage(), ex);
                    }
		}
		
		private void loadConnectionPreferences() throws Exception {
			ConnectionData c = this.getConnectionData();
                        if (c == null) {
                            return;
                        }
			textFieldHost.setText(c.getHost());
			textFieldPort.setText(c.getPort().toString());
			textFieldUser.setText(c.getUser());
			passwordField.setText(c.getPassword());
		}
		
		private ConnectionData getConnectionData() throws Exception {
			File connectionFile = new File(
					LocalFileUtil.getPreferenceFolder().getAbsolutePath() + "/connection.xml");
			if (!connectionFile.exists()) {
                            return null;
                        }
                        return XmlFacade.readConnectionDataXml(connectionFile);
		}
    }
    
    private class ConnectAction implements ActionListener {

                @Override
		public void actionPerformed(ActionEvent e) {
                    if (!this.fieldValidation()) {
                        return;
                    }
			this.setConnectionProperties();
                        ServerFacade.connect();

                        if (!Main.getConnectionData().isConnected()) {
                            return;
                        }

			try {
				this.loadLocalFilesView();
				this.loadRemoteFilesView();
				this.persistConnectionData();
			} catch (Exception ex) {
				String message = "Não foi possível abrir conexão com o servidor de FTP.\nDetalhe: " + ex.getMessage();
				MensagensUtil.showErrorMessage("Erro de conexão", message);
				logger.log(Level.SEVERE, ex.getMessage(), ex);
				return;
			}
			
			dispose();
		}
		
		private void loadLocalFilesView() {
			String path = new File("").getAbsolutePath();
			
			MainFrame
				.getInstance()
				.getTableLocalFiles()
				.setModel(FileTableModelBuilder
						.createLocalFilesTableModel(path));
			
			String[] tokenPath = path.split("/");
			Stack<String> stack = MainFrame.getInstance().getLocalFilePath();
			stack.clear();
			for (String token : tokenPath) {
				if (!token.equals("")) {
					stack.push(token);
				}
			}
		}
		
		private void loadRemoteFilesView() {
			String path = "";
			
			MainFrame
				.getInstance()
				.getTableRemoteFiles()
				.setModel(FileTableModelBuilder
						.createRemoteFilesTableModel(path));
			
			String[] tokenPath = path.split("/");
			Stack<String> stack = MainFrame.getInstance().getRemoteFilePath();
			stack.clear();
			for (String token : tokenPath) {
				if (!token.equals("")) {
					stack.push(token);
				}
			}
		}
		
		private void setConnectionProperties() {
			ConnectionData c = Main.getConnectionData();
			c.setUser(textFieldUser.getText());
			c.setPassword(new String(passwordField.getPassword()));
			c.setHost(textFieldHost.getText());
			c.setPort(Integer.parseInt(textFieldPort.getText()));
		}
		
		private void persistConnectionData() throws IOException {
			XmlFacade.writeConnectionDataToXml(
					Main.getConnectionData(), this.getConnectionDataFile());
		}
		
		private File getConnectionDataFile() {	        
	        return new File(LocalFileUtil.
	        		getPreferenceFolder().
	        		getAbsolutePath() + "/" + "connection.xml");
		}

                private boolean fieldValidation() {
                    if (textFieldUser.getText().isEmpty()) {
                        MensagensUtil.showWarningMessage("Validação", "É necessário informar um usuário.");
                        return false;
                    }

                    if (textFieldHost.getText().isEmpty()) {
                        MensagensUtil.showWarningMessage("Validação", "É necessário informar um host.");
                        return false;
                    }

                    String port = textFieldPort.getText();
                    if (port.isEmpty()) {
                        MensagensUtil.showWarningMessage("Validação", "É necessário informar uma porta para conexão.");
                        return false;
                    }

                    try {
                        Integer.parseInt(port);
                    } catch (NumberFormatException ex) {
                        MensagensUtil.showWarningMessage("Validação", "O valor informado para porta (" + port + ") não é um número inteiro válido.");
                        return false;
                    }

                    return true;
                }
    }
}